/*
 * "Copyright (c) 2012 Universitat Pompeu Fabra.
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 *
 * IN NO EVENT SHALL UNIVERSITAT POMPEU FABRA BE LIABLE TO ANY PARTY 
 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING 
 * OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF POMPEU FABRA
 * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * UNIVERSITAT POMPEU FABRA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND UNIVERSITAT POMPEU FABRA HAS NO OBLIGATION TO 
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 */
 
#include "HbcpNetworkPackets.h"
#include "HbcpStatistics.h"

module CC2420LinkP{
	provides{
		interface HbcpLink as Send;
		interface Receive as LinkReceive;
		interface Init;	
	}
	uses{
		interface Receive;
		interface AMSend as RadioAMSend;
		interface SplitControl;
		interface Packet;
		interface PacketAcknowledgements;
		interface AMPacket;
		interface PacketLink;
		interface CC2420Packet;
		interface Random;
		interface ParameterInit<uint16_t> as SeedInit;
	}
}

implementation{

	message_t msgBuf;
	message_t* message;
	uint8_t msgLen;
	am_addr_t msgAddress;
	bool isBusy = FALSE;

	command error_t Init.init(){
		call SplitControl.start();
		call SeedInit.init(TOS_NODE_ID);
        return SUCCESS;
    }

	command error_t Send.send(am_addr_t addr, void *payload, uint8_t len){		
		
		if(isBusy){
			return FAIL;
		}
		isBusy = TRUE;
		
		call AMPacket.setSource(&msgBuf, TOS_NODE_ID);
		
		if(addr == AM_BROADCAST_ADDR){
			call PacketAcknowledgements.noAck(&msgBuf);
			call PacketLink.setRetries(&msgBuf, 0);
		}
		else{
			call PacketAcknowledgements.requestAck(&msgBuf);
			call PacketLink.setRetries(&msgBuf, HbcpRetries);
            //call PacketLink.setRetryDelay(&msgBuf, call Random.rand16() % HbcpRetryDelay);
		}
		
		call CC2420Packet.setPower(&msgBuf, TX_POWER);
		memcpy(call Packet.getPayload(&msgBuf, len),payload,len);
		
		if(addr != AM_BROADCAST_ADDR){
			stats.packetsTx++;
		}		
		return call RadioAMSend.send(addr, &msgBuf, len);
	}
    
    event void RadioAMSend.sendDone(message_t* msg, error_t status) {
    	
    	if(call AMPacket.destination(msg)!= AM_BROADCAST_ADDR && call PacketAcknowledgements.wasAcked(msg)){
            stats.packetsAcked++;
    	}
        isBusy=FALSE;
    }
    
	event message_t * Receive.receive(message_t *msg, void *payload, uint8_t len){
		signal LinkReceive.receive(msg, payload, len);
		return msg;
	}
	   
    event void SplitControl.stopDone(error_t error){}
    event void SplitControl.startDone(error_t error){}
	
}